package com.teradata.config;

import com.teradata.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import static org.springframework.web.reactive.function.server.ServerResponse.ok;

/**
 * Web Flux Config
 */
@Slf4j
@Configuration
public class WebFluxConfig implements WebFilter{

    @Bean
    public RouterFunction helloworldRouterFunction() {
        /*RequestPredicate requestPredicate = GET("/webflux");
        HandlerFunction handlerFunction = new HandlerFunction() {
            // 处理请求
            @Override
            public Mono handle(ServerRequest request) {
                //request.headers().host().getAddress().getAddress()
                return ok().body(Mono.just("Hello"),String.class);
            }
        };
        return route(requestPredicate,handlerFunction );*/

        //return route(GET("/webflux"), request -> ok().body(Mono.just("Hello, World api:" + request.queryParam("api").orElse("qichao")), String.class));


        return route(GET("/webflux"), request -> ok().body(Mono.just(request + " said to " + request.headers().host().getHostString() + " Hello! And it is "), String.class));
    }

    @Bean
    public RouterFunction userRouterFunction() {
        /*return route(POST("/webflux/user"),
                request -> {
                    // JSON 格式表达 User
                    Mono<User> userMono = request.bodyToMono(User.class);
                    // User Java toString() 表达响应对象
                    Mono<String> stringMono = userMono.map(User::toString);
                    return ok().body(stringMono,String.class);
                });*/

        return route(POST("/webflux/user"),
                request -> ok().body(
                        request.bodyToMono(User.class)
                                .subscribeOn(Schedulers.parallel())
                                .map(User::toString),
                        String.class)
        );

        //immediate()
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}

        //single()
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :single-1 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :single-1 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}

        //elastic()
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :elastic-2 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :elastic-2 ] : User{id='1234', name='huzhengyang', email='null'}

        //parallel()
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :parallel-1 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :parallel-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :reactor-http-nio-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :parallel-1 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :parallel-2 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :parallel-3 ] : User{id='1234', name='huzhengyang', email='null'}
        //[Thread :parallel-4 ] : User{id='1234', name='huzhengyang', email='null'}


    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        if (log.isInfoEnabled()) {
            //return chain.filter(decorate(exchange));
            return null;
        } else {
            return chain.filter(exchange);
        }
    }
}
